优雅简洁的列表推导式
优雅的列表推导式
最近比较累,给自己放了很长的假。使用廖雪峰网站学习时一开始学过列表推导式这方面的知识,但不知道有什么用,也没觉得好看简洁。但接触的多了,用的多了之后,发现推导式确实好用。
使用推导式可以简化代码,方便阅读理解。借助推导式,可以代替以下功能:
替换for循环,压缩代码行数
使用lambda表达式,实现map()、filter()、reduce(),代码便于理解
一、替换for循环
因为简单易用,列表是python中常用的数据类型。但是列表往往需要使用for循环代码块,第一个缺点是代码可读性降低,第二个缺点是代码行数大大增加。
使用列表推导式就能消除以上两点,而且效率还会略有提高。
我们先看一个例子,[0,1,2,3,4,5,6,7,8,9]中选取偶数,并计算偶数的平方将其加到一个新列表中。我们先看看常见的实现方式
#生成0-9的列表
numbers = range(10)
new_list = []
#将计算结果加到new_list中
for n in numbers:
if n%2==0:
new_list.append(n**2)
print(new_list)
[0, 4, 16, 36, 64]
再来看看推导式实现方式
numbers = range(10)
new_list = [n**2 for n in numbers if n%2==0]
print(new_list)
只用了三行就实现了上面好多行的代码应有的功能。
[0, 4, 16, 36, 64]
我们再来比较下运行效率,为了方便计算,我们将使用timeit模块计算两者运行10000次所消耗时间的大小,用时最少表示其运行效率更高。
import timeit
#推导式运行时间
print(timeit.timeit('[n**2 for n in range(10) if n%2==0]', number=10000))
#for代码
def forcodeblock():
new_list = []
for n in range(10):
if n%2==0:
new_list.append(n**2)
return new_list
#for代码块运行时间
print(timeit.timeit('forcodeblock()',globals=globals(),numbers=10000))
0.05234622399802902
0.07795589299712447
看,用列表推导式运行时间更短,更快。
二、实现map()的功能
lambda表达式功能类似于函数,但是没有名字的函数。我们在推导式中可以加入lambda表达式,进而实现map()的功能。
map(function,iterable)
map函数是对iterable中的每一个元素施行function函数计算,返回可迭代结果(如列表)。
直接看例子,解说map及推导式的实现方式
公制时间转换,将以秒计算单位转化为以分钟计时,需要除以60.
#存储时间的列表
time_list = [60,120,3600,1200,600]
#使用map实现
new_time_list = map(lambda x:x/60, time_list)
print(new_time_list)
[1,2,60,20,10]
再来看看推导式实现方式:
#存储时间的列表
time_list = [60,120,3600,1200,600]
#使用map实现
new_time_list = [x/60 for x in time_list]
print(new_time_list)
三、实现filter()功能
filter意思是过滤剔除。
filter(function,iterable)
filter跟map类似,对iterable每个元素计算function(该函数计算结果为布尔值),如果该元素function值为布尔值为1,则保留该元素。最终输出所有保留的元素。
现在我们看一个0-9的数组,只保留奇数。
numbers = range(10)
#奇数
uneven = filter(lambda x:x%2,numbers)
print(uneven)
[1,3,5,7,9]
再来看看,列表推导式实现filter。这里只给出列表中对应位置元素值为1.
uneven = [x for x in numbers if x%2]
print(uneven)
[1,3,5,7,9]
四、实现reduce()功能
reduce(function,iterable)功能不好说,我举个例子,大家自己琢磨一下。
#对[1,2,3,4]进行求和运算,使用reduce是这样子的。
(((1+2)+3)+4)
reduce不限于四则运算,只要reduce第一个参数是运算规则,第二个参数是可迭代对象
from functools import reduce
#对0-9进行求和
numbers = range(10)
reduced_sum = reduce(lambda x,y:x+y, numbers)
print(reduced_sum)
推导式方式代码:
numbers = range(10)
reduced_sum = sum([x for x in numbers])
五、带条件的推导式
5.1 一个条件
numbers = range(10)
#奇数
uneven = [x/2 for x in numbers if x%2==0]
print(uneven)
numbers = range(10)
#奇数
uneven = []
for x in numbers:
if x % 2 == 0:
x = x / 2
uneven.append(x)
print(uneven)
5.2 多个条件
#0-9中同时被2和6整除的数
divided = []
for x in range(10):
if x%2 == 0 :
if x%6 == 0:
divided.append(x)
#0-9中同时被2和6整除的数
divided = [x for x in range(10) if x%2==0 if x%6==0]
5.3 if-else
推导式很少看到if-else,如果想实现if-else该咋整。if-elif-else与if-else类似。直接看案例
for x in range(10):
if x >= 5:
x + 1
else:
x+5
推导式实现
[x+1 if x>=5 else x+5 for x in range(10)]
六、嵌套推导式
有时候要处理列表的列表,这个有点难度。比如生成列表的列表,对矩阵进行转置,或者flatten矩阵为列表。
6.1 flatten
list_of_list = [[1,2,3],[4,5,6],[7,8]]
#flatten
print([y for x in list_of_list for y in x])
[1, 2, 3, 4, 5, 6, 7, 8]
6.2 生成矩阵
生成3行4列的矩阵,常规手法
matrix=[]
for x in range(3):
nested = []
matrix.append(nested)
for row in range(4):
nested.append(0)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
推导式实现
matrix=[[0 for col in range(4)] for row in range(3)]
print(matrix)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
6.3 矩阵转置
在矩阵中,行列互换。
[[1,2,3],
[4,5,6],
[7,8,9]]
变成
[[1, 4, 7],
[2, 5, 8],
[3, 6, 9]]
常规的实现方式转置
transposed = []
for i in range(3):
transposed_row = []
for row in matrix:
transposed_row.append(row[i])
transposed.append(transposed_row)
推导式实现矩阵转置
list_of_list = [[1,2,3],[4,5,6],[7,8,9]]
print([[row[i] for row in matrix] for i in range(3)])
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
历史文章:
数据采集
【视频】有了selenium,小白也可以自豪的说:“去TMD的抓包、cookie”
【视频】快来get新技能--抓包+cookie,爬微博不再是梦